
/*
 *
 * Copyright (C) 2008 Mattias Blomqvist, patr-blo at dsv dot su dot se
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using FlowLib.Containers;
using FlowLib.Connections;
using System.Threading;
using ClientExample.Containers;
using ClientExample.Controls;

namespace ClientExample.Client.Interface
{
    public partial class MainWindow : Form
    {
        protected MessageWindow msgWindow = new MessageWindow();
        protected SearchResultWindow schResultWindow = new SearchResultWindow();
        protected SearchExtended schExdWindow = new SearchExtended();
		
		protected ContextMenu notificationMenu = new ContextMenu();
		protected bool isNotificationMenuShowed = false;

        protected delegate void AddingListItem();

        protected List<HubSetting> savedHubs = null;
        protected List<HubControl> activeHubs = new List<HubControl>();
        protected FriendsControl friends = new FriendsControl();
        protected bool isUpdating = false;
        protected System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
        protected bool allowClosing = false;

        protected static string currVersion = "20091127";
        protected static MainWindow currInstance = null;

        public static string CurrentVersion
        {
            get { return currVersion; }
            set { currVersion = value; }
        }

        public static MainWindow CurrentInstance
        {
            get { return currInstance; }
        }

        public MainWindow()
        {
			IntPtr h = Handle;  // This is for stupid mono stuff. Some how handle isnt created correctly if we dont do this :(
			
            Program.Settings.Version = CurrentVersion;
            Program.Save();

            InitializeComponent();
            LoadLocationAndSize();

            btnQuickConnect.ImageDirectory = "Images.DarkBlue.";

            currInstance = this;

            // Scroll hub list
            searchBox1.MouseWheel += new MouseEventHandler(searchBox1_MouseWheel);

            msgWindow.VisibleChanged += new EventHandler(OnChildWindowVisibleChanged);
            schResultWindow.VisibleChanged += new EventHandler(OnChildWindowVisibleChanged);
            schExdWindow.VisibleChanged += new EventHandler(OnChildWindowVisibleChanged);

            this.LocationChanged += new EventHandler(MainWindow_LocationChanged);

            notificationMenu.MenuItems.Add("Show Messages", new EventHandler(OnShowMsgWindow));
            MenuItem showXmpl = new MenuItem("Open Xmpl");
            showXmpl.DefaultItem = true;
            showXmpl.Click += new EventHandler(OnShowMainWindow);
            notificationMenu.MenuItems.Add(showXmpl);

            notificationMenu.MenuItems.Add("Reset Xmpl position", new EventHandler(OnWindowPositionReset));

			notificationMenu.MenuItems.Add("Exit", new EventHandler(OnExit));
			notificationMenu.Popup += new EventHandler(OnNotificationPopup);
			
            notifyIcon1.Icon = this.Icon;
            notifyIcon1.MouseClick += new MouseEventHandler(notifyIcon1_MouseClick);
			notifyIcon1.ContextMenu = notificationMenu;

            // Add friends control
            list1.Items.Add(friends);

            searchBox1.ActionUpdate += new FlowLib.Events.FmdcEventHandler(OnSearchControlUpdate);

            if (Program.Settings.SavedHubs != null)
                savedHubs = new List<HubSetting>(Program.Settings.SavedHubs);
            else
                savedHubs = new List<HubSetting>();

            if (savedHubs.Count == 0)
            {
                HubSetting set2 = new HubSetting();
                set2.Name = "- DC Dev Public -";
                set2.Address = "devpublic.adcportal.com";
                set2.Port = 16591;
                set2.Protocol = "AdcSecure";
                set2.DisplayName = "Xmpl-" + Guid.NewGuid().ToString();

                set2.Set("Connect", "1");
                savedHubs.Add(set2);
                Program.Settings.SavedHubs.Add(set2);
            }

            timer.Tick += new EventHandler(timer_Tick);
            timer.Interval = 200;
            timer.Start();
        }

        void searchBox1_MouseWheel(object sender, MouseEventArgs e)
        {
            list1.SetScroll(e.Delta);
        }

        void MainWindow_LocationChanged(object sender, EventArgs e)
        {
            switch (Program.Settings.LocationType)
            {
                case 0:     // Absolute Location
                    break;
                case 1:     // Relative Location
                    SaveLocationAndSize();
                    LoadLocationAndSize(false);
                    break;
            }
        }

        void LoadLocationAndSize()
        {
            LoadLocationAndSize(true);
        }
        void LoadLocationAndSize(bool firstTime)
        {
            // Main Window
            if (firstTime)
            {
                if (
                    Program.Settings.MainWindowLocation.X +
                    Program.Settings.MainWindowLocation.Y +
                    Program.Settings.MainWindowSize.Width +
                    Program.Settings.MainWindowSize.Height > 0)
                {
                    SetDesktopBounds(Program.Settings.MainWindowLocation.X, Program.Settings.MainWindowLocation.Y, Program.Settings.MainWindowSize.Width, Program.Settings.MainWindowSize.Height);
                }
            }
            // Msg Window
            if (
                Program.Settings.MsgWindowLocation.X +
                Program.Settings.MsgWindowLocation.Y +
                Program.Settings.MsgWindowSize.Width +
                Program.Settings.MsgWindowSize.Height > 0)
            {
                switch (Program.Settings.LocationType)
                {
                    case 0:
                        if (firstTime)
                            msgWindow.SetDesktopBounds(Program.Settings.MsgWindowLocation.X, Program.Settings.MsgWindowLocation.Y, Program.Settings.MsgWindowSize.Width, Program.Settings.MsgWindowSize.Height);
                        break;
                    case 1:
                        if (firstTime)
                        {
                            msgWindow.SetDesktopBounds(
                                this.DesktopBounds.Location.X + Program.Settings.MsgWindowLocation.X,
                                this.DesktopBounds.Location.Y + Program.Settings.MsgWindowLocation.Y,
                                Program.Settings.MsgWindowSize.Width, Program.Settings.MsgWindowSize.Height);
                        }
                        else
                        {
                            //msgWindow.Left = this.DesktopBounds.Location.X + Program.Settings.MsgWindowLocation.X;
                            //msgWindow.Top = this.DesktopBounds.Location.Y + Program.Settings.MsgWindowLocation.Y;
                            //msgWindow.Show();
                            //msgWindow.WindowState = FormWindowState.Normal;

                            //msgWindow.Location = new Point(
                            //    this.DesktopBounds.Location.X + Program.Settings.MsgWindowLocation.X,
                            //    this.DesktopBounds.Location.Y + Program.Settings.MsgWindowLocation.Y
                            //    );
                            //msgWindow.SetDesktopLocation(
                            //    this.DesktopBounds.Location.X + Program.Settings.MsgWindowLocation.X,
                            //    this.DesktopBounds.Location.Y + Program.Settings.MsgWindowLocation.Y
                            //    );
                        }
                        break;
                }
            }
            // Seach Results Window
            if (
                Program.Settings.SchResultWindowLocation.X +
                Program.Settings.SchResultWindowLocation.Y +
                Program.Settings.SchResultWindowSize.Width +
                Program.Settings.SchResultWindowSize.Height > 0)
            {
                switch (Program.Settings.LocationType)
                {
                    case 0:
                        if (firstTime)
                            schResultWindow.SetDesktopBounds(Program.Settings.SchResultWindowLocation.X, Program.Settings.SchResultWindowLocation.Y, Program.Settings.SchResultWindowSize.Width, Program.Settings.SchResultWindowSize.Height);
                        break;
                    case 1:
                        schResultWindow.SetDesktopBounds(
                            Program.Settings.MainWindowLocation.X + Program.Settings.SchResultWindowLocation.X,
                            Program.Settings.MainWindowLocation.Y + Program.Settings.SchResultWindowLocation.Y,
                            Program.Settings.SchResultWindowSize.Width, Program.Settings.SchResultWindowSize.Height);
                        break;
                }
            }
            // Seach Ext Window
            if (
                Program.Settings.SchExtWindowLocation.X +
                Program.Settings.SchExtWindowLocation.Y +
                Program.Settings.SchExtWindowSize.Width +
                Program.Settings.SchExtWindowSize.Height > 0)
            {
                switch (Program.Settings.LocationType)
                {
                    case 0:
                        if (firstTime)
                            schExdWindow.SetDesktopBounds(Program.Settings.SchExtWindowLocation.X, Program.Settings.SchExtWindowLocation.Y, Program.Settings.SchExtWindowSize.Width, Program.Settings.SchExtWindowSize.Height);
                        break;
                    case 1:
                        schExdWindow.SetDesktopBounds(
                            Program.Settings.MainWindowLocation.X + Program.Settings.SchExtWindowLocation.X,
                            Program.Settings.MainWindowLocation.Y + Program.Settings.SchExtWindowLocation.Y,
                            Program.Settings.SchExtWindowSize.Width, Program.Settings.SchExtWindowSize.Height);
                        break;
                }
            }
        }

        void SaveLocationAndSize()
        {
            // Main Window
            Program.Settings.UpdateSequence = true;
            Program.Settings.MainWindowLocation = DesktopBounds.Location;
            Program.Settings.MainWindowSize = DesktopBounds.Size;

            switch (Program.Settings.LocationType)
            {
                case 0:     // Absolute Location
                    // Msg Window
                    Program.Settings.MsgWindowLocation = msgWindow.DesktopBounds.Location;
                    Program.Settings.MsgWindowSize = msgWindow.DesktopBounds.Size;
                    // Search Results Window
                    Program.Settings.SchResultWindowLocation = schResultWindow.DesktopBounds.Location;
                    Program.Settings.SchResultWindowSize = schResultWindow.DesktopBounds.Size;
                    // Search Ext Window
                    Program.Settings.SchExtWindowLocation = schExdWindow.DesktopBounds.Location;
                    Program.Settings.SchExtWindowSize = schExdWindow.DesktopBounds.Size;
                    break;
                case 1:     // Relative Location
                    // Msg Window
                    Point msgWindowLocation = msgWindow.DesktopBounds.Location;
                    msgWindowLocation.X -= DesktopBounds.Location.X;
                    msgWindowLocation.Y -= DesktopBounds.Location.Y;
                    Program.Settings.MsgWindowLocation = msgWindowLocation;
                    // Search Results Window
                    Point schResultWindowLocation = schResultWindow.DesktopBounds.Location;
                    schResultWindowLocation.X -= DesktopBounds.Location.X;
                    schResultWindowLocation.Y -= DesktopBounds.Location.Y;
                    Program.Settings.SchResultWindowLocation = schResultWindowLocation;
                    // Search Ext Window
                    Point schExtWindowLocation = schExdWindow.DesktopBounds.Location;
                    schExtWindowLocation.X -= DesktopBounds.Location.X;
                    schExtWindowLocation.Y -= DesktopBounds.Location.Y;
                    Program.Settings.SchExtWindowLocation = schExtWindowLocation;
                    break;
            }
            // Msg Window
            Program.Settings.MsgWindowSize = msgWindow.DesktopBounds.Size;
            // Search Results Window
            Program.Settings.SchResultWindowSize = schResultWindow.DesktopBounds.Size;
            // Search Ext Window
            Program.Settings.SchExtWindowSize = schExdWindow.DesktopBounds.Size;
            Program.Settings.UpdateSequence = false;
        }

        void OnChildWindowVisibleChanged(object sender, EventArgs e)
        {
            Form window = sender as Form;
            if (window != null && !window.Visible)
                SaveLocationAndSize();
        }

        public void Exit()
        {
            allowClosing = true;
            Close();
        }

		void OnExit(object sender, EventArgs e)
		{
            Exit();
		}

        void OnWindowPositionReset(object sender, EventArgs e)
        {
            this.DesktopLocation = Screen.PrimaryScreen.WorkingArea.Location;
            SaveLocationAndSize();
        }

        void OnShowMsgWindow(object sender, EventArgs e)
        {
            ShowMessageWindow();
        }
			
		void OnShowMainWindow(object sender, EventArgs e)
		{
            ShowMainWindow();
		}
						
		void OnNotificationPopup(object sender, EventArgs e)
		{
			//Console.WriteLine("OnNotificationPopup");
		}

        void OnSearchControlUpdate(object sender, FlowLib.Events.FmdcEventArgs e)
        {
            switch (e.Action)
            {
                case EventActions.Search:
                    SearchInfo info = e.Data as SearchInfo;
                    if (info == null)
                        return;
                    schResultWindow.AddSearch(info);
                    List<HubControl> hubs = new List<HubControl>(activeHubs);
                    foreach (HubControl hub in hubs)
                    {
                        hub.SendSearch(info);
                    }
                    hubs.Clear();
                    hubs = null;
                    ShowSearchResultsWindow();
                    break;
                case EventActions.SearchExtended:
                    ShowSearchExtendWindow();
                    break;
            }
        }

        void notifyIcon1_MouseClick(object sender, MouseEventArgs e)
        {
//			System.Console.WriteLine(e.Button);
/*
            if (e.Button == MouseButtons.Left)
            {
					ShowMainWindow();
            }
            else if (e.Button == MouseButtons.Right)
            {
                this.allowClosing = true;
                this.Close();
            }
*/
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            if (allowClosing)
            {
                notifyIcon1.ShowBalloonTip(5 * 1000, "Xmpl", "Xmpl is shutting down in 5 seconds", ToolTipIcon.Info);
                Thread.Sleep(5 * 1000);
				Program.Save(true);
                base.OnClosing(e);
            }
            else
            {
                SaveLocationAndSize();
                e.Cancel = true;
                //notifyIcon1.Visible = true;
                notifyIcon1.ShowBalloonTip(5 * 1000, "Xmpl", "Xmpl is still running.\r\nRight click icon to shutdown Xmpl.", ToolTipIcon.Info);
                this.Hide();
            }
        }

        void timer_Tick(object sender, EventArgs e)
        {
            if (isUpdating)
                return;
            isUpdating = true;
            if (savedHubs.Count > 0)
            {
                lock (savedHubs)
                {
                    HubSetting item = savedHubs[0];
                    savedHubs.RemoveAt(0);
                    AddHub(item);
                }
            }
            else
            {
                timer.Dispose();
            }
            isUpdating = false;
        }

        void hub_HubUpdate(object sender, FlowLib.Events.FmdcEventArgs e)
        {
            ClientExample.Controls.HubControl hub = sender as ClientExample.Controls.HubControl;
            if (hub == null)
                return;
            switch (e.Action)
            {
                case EventActions.Close:
                    hub.HubUpdate -= hub_HubUpdate;
                    list1.Items.Remove(hub);
                    break;
                case EventActions.ForceOpenMessage:
                    if (msgWindow.WindowState == FormWindowState.Minimized || !msgWindow.Visible)
                    {
                        ShowMessageWindow();
                    }
                    break;
                case EventActions.OnlineStatusChange:      // Update Status
                    OnlineStatus onlineStatus = e.Data as OnlineStatus;
                    if (onlineStatus == null)
                        return;
                    if (onlineStatus.Status == TcpConnection.Disconnected && hub.IsConnectionDisposing)
                        hub.HubUpdate -= schResultWindow.OnHubUpdate;
                    break;
            }
        }

        protected void OnLoad()
        {
        }

        private void MainWindow_Load(object sender, EventArgs e)
        {
            // Quick Connect Button
            btnQuickConnect.ImageDirectory = "Images.DarkBlue.";
            btnQuickConnect.MouseClick += new MouseEventHandler(btnQuickConnect_MouseClick);
            // Messages Button
            btnMessages.ImageDirectory = "Images.DarkBlue.";
            btnMessages.MouseClick += new MouseEventHandler(btnMessages_MouseClick);
            // Search Results Button
            btnSearchResults.ImageDirectory = "Images.DarkBlue.";
            btnSearchResults.MouseClick += new MouseEventHandler(btnSearchResults_MouseClick);

            btnUninstall.ImageDirectory = "Images.DarkBlue.";
            btnUninstall.MouseClick += new MouseEventHandler(btnUninstall_MouseClick);
            //btnQuickConnect1.Image = Program.Images.GetBitmap("quickconnect.gif");
            //btnMessages1.Image = Program.Images.GetBitmap("pen.gif");
            //btnSearchResults1.Image = Program.Images.GetBitmap("searchresults.gif");
        }

		public void ShowMainWindow()
		{
			this.Show();
            this.Focus();
            //notifyIcon1.Visible = !this.Visible;
		}

		public HubControl AddHub(HubSetting item)
        {
            list1.SuspendLayout();
            //HubSetting item = savedHubs[0];
            //savedHubs.RemoveAt(0);

            HubControl hub = new HubControl();
			while (hub.Handle == null) { }
            bool showUserlist = hub.Expanded;       // True
            if (item.ContainsKey("UserListState") && item.Get("UserListState").Equals("1"))
            {

            }
            else
                hub.Expanded = !hub.Expanded;
            hub.Setting = item;
            msgWindow.AddHub(hub);
            schResultWindow.AddHub(hub);
            friends.AddHub(hub);
            activeHubs.Add(hub);
            Program.Transfers.AddHub(hub);

            hub.HubUpdate += new FlowLib.Events.FmdcEventHandler(hub_HubUpdate);

            list1.Items.Add(hub);
            list1.ResumeLayout();
            return hub;
        }

        public void ShowMessageWindow()
        {
            Screen screen = Screen.FromControl(this);
            int pos = this.Left + this.Width + msgWindow.Width;
            msgWindow.Show();
            msgWindow.WindowState = FormWindowState.Normal;
            // Only set this window pos first time
            if (Program.Settings.MsgWindowSize.Width + Program.Settings.MsgWindowSize.Height == 0)
            {
                if (pos < screen.WorkingArea.Left + screen.WorkingArea.Width)
                    msgWindow.Location = new Point(this.Left + this.Width, this.Top);
                else
                    msgWindow.Location = new Point(this.Left - msgWindow.Width, this.Top);
            }
            msgWindow.Focus();
        }

        public void ShowSearchResultsWindow()
        {
            Screen screen = Screen.FromControl(this);
            int pos = this.Left + this.Width + schResultWindow.Width;
            schResultWindow.Show();
            schResultWindow.WindowState = FormWindowState.Normal;
            // Only set this window pos first time
            if (Program.Settings.SchResultWindowSize.Width + Program.Settings.SchResultWindowSize.Height == 0)
            {
                if (pos < screen.WorkingArea.Left + screen.WorkingArea.Width)
                    schResultWindow.Location = new Point(this.Left + this.Width, this.Top);
                else
                    schResultWindow.Location = new Point(this.Left - schResultWindow.Width, this.Top);
            }
            schResultWindow.Focus();
        }

        public void ShowSearchExtendWindow()
        {
            Screen screen = Screen.FromControl(this);
            int pos = this.Left + this.Width + schExdWindow.Width;
            schExdWindow.Show();
            schExdWindow.WindowState = FormWindowState.Normal;
            // Only set this window pos first time
            if (Program.Settings.SchExtWindowSize.Width + Program.Settings.SchExtWindowSize.Height == 0)
            {
                if (pos < screen.WorkingArea.Left + screen.WorkingArea.Width)
                    schExdWindow.Location = new Point(this.Left + this.Width, this.Top);
                else
                    schExdWindow.Location = new Point(this.Left - schExdWindow.Width, this.Top);
            }
            schExdWindow.Focus();
        }

        public void QuickConnect()
        {
            QuickConnect(new HubSetting());
        }

        public void QuickConnect(HubSetting setting)
        {
            //HubSetting setting = new HubSetting();
            HubSettingsWindow dlg = new HubSettingsWindow();
            dlg.Settings = setting;
            if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                setting = dlg.Settings;
                setting.Set("QuickConnect", "1");

                HubControl hub = AddHub(setting);
                Program.Settings.SavedHubs.Add(setting);
                Program.Save();
            }
        }

        void btnQuickConnect_MouseClick(object sender, MouseEventArgs e)
        {
            QuickConnect();
        }

        private void btnMessages_MouseClick(object sender, EventArgs e)
        {
            ShowMessageWindow();
        }

        private void btnSearchResults_MouseClick(object sender, EventArgs e)
        {
            ShowSearchResultsWindow();
        }

        void btnUninstall_MouseClick(object sender, MouseEventArgs e)
        {
            Program.Uninstall();
            MessageBox.Show("Xmpl has now been uninstalled.");
            Exit();
        }
    }
}
